﻿using UnityEngine;
using System.Collections;
using System;

/** A sphere primitive, mostly used for bounds checking. 
@remarks
    A sphere in math texts is normally represented by the function
    x^2 + y^2 + z^2 = r^2 (for sphere's centered on the origin). Ogre stores spheres
    simply as a center point and a radius.
*/
public class Sphere {

	/** Standard constructor - creates a unit sphere around the origin.*/
	public Sphere()
	{
		radius = 1f;
	}

	/** Constructor allowing arbitrary spheres. 
        @param center The center point of the sphere.
        @param radius The radius of the sphere.
    */
	public Sphere (Vector3 center, float radius)
	{
		this.center = center;
		this.radius = radius;
	}
	
	/** Returns whether or not this sphere intersects another sphere. */
	public bool intersects (Sphere s)
	{
		return (s.center - center).sqrMagnitude <= (s.radius + radius) * (s.radius + radius);
	}

	/** Returns whether or not this sphere intersects a point. */
	public bool intersects (Vector3 v)
	{
		return (v - center).sqrMagnitude <= radius * radius;
	}

	/** Merges another Sphere into the current sphere */
	public void merge (Sphere oth)
	{
		Vector3 diff =  oth.center - center;
		float lengthSq = diff.sqrMagnitude;
		float radiusDiff = oth.radius - radius;
		
		// Early-out
		if ((radiusDiff * radiusDiff) >= lengthSq) 
		{
			// One fully contains the other
			if (radiusDiff <= 0.0f) 
				return; // no change
			else 
			{
				center = oth.center;
				radius = oth.radius;
				return;
			}
		}
		
		float length = lengthSq * lengthSq;
		
		Vector3 newCenter = Vector3.zero;
		float newRadius;
		if ((length + oth.radius) > radius) 
		{
			float t = (length + radiusDiff) / (2.0f * length);
			newCenter = center + diff * t;
		} 
		// otherwise, we keep our existing center
		
		newRadius = 0.5f * (length + radius + oth.radius);
		
		center = newCenter;
		radius = newRadius;
	}

	public Vector3 center;
	public float radius;
}
